package com.workflow.server.service.impl;

import com.workflow.server.bean.dto.ChildNode;
import com.workflow.server.exception.ProcessValidationException;
import com.workflow.server.service.IFlowNodeCreateHandler;
import com.workflow.server.service.IFlowNodeCreateHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.model.bpmn.instance.FlowNode;
import org.camunda.bpm.model.bpmn.instance.Process;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * @author: ForeverKobe
 * <p>title:流程节点创建处理器上下文</p>
 * 实现流程节点创建处理器上下文，主要用于根据节点类型创建对应的流程节点
 */
@Slf4j
@Component
public class FlowNodeCreateHandlerContextImpl implements IFlowNodeCreateHandlerContext, CommandLineRunner {
    /**
     * 存储节点类型与创建处理器的映射关系
     */
    private static final Map<String, IFlowNodeCreateHandler> nodeCreateHandlerMap = new HashMap<>();

    /**
     * 注入应用上下文，用于获取所有节点创建处理器
     */
    @Autowired
    ApplicationContext applicationContext;

    /**
     * 根据子节点类型创建流程节点
     *
     * @param parentNodeId 父节点ID
     * @param childNode 子节点信息
     * @param process 流程定义
     * @param childNodeMap 所有子节点信息映射
     * @return 创建的流程节点
     */
    @Override
    public FlowNode createNode(String parentNodeId, ChildNode childNode, Process process, Map<String, ChildNode> childNodeMap) {
        checkNodeType(childNode);
        IFlowNodeCreateHandler flowNodeCreateHandler = nodeCreateHandlerMap.get(childNode.getType());
        // 根据子节点类型获取对应的创建处理器，并调用其创建节点方法
        return flowNodeCreateHandler.createNode(parentNodeId, childNode, process, childNodeMap);
    }

    public void checkNodeType(ChildNode childNode) throws ProcessValidationException {
        if (nodeCreateHandlerMap.get(childNode.getType()) == null){
            throw new ProcessValidationException("节点类型[" + childNode.getType() + "]不存在");
        }
    }

    @Override
    public void run(String... args) {
        // 获取应用上下文中所有节点创建处理器类型的Bean
        Map<String, IFlowNodeCreateHandler> beansOfType = applicationContext.getBeansOfType(IFlowNodeCreateHandler.class);
        // 遍历并填充节点类型与创建处理器的映射
        beansOfType.forEach((k, v) -> nodeCreateHandlerMap.put(v.getType(), v));
        log.info("加载流程节点处理策略:[{}]", nodeCreateHandlerMap);
    }
}
